package org.example.campusforum.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.mail.MailException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.example.campusforum.common.Result;
import org.example.campusforum.dto.*;
import org.example.campusforum.entity.ToEmail;
import org.example.campusforum.entity.User;
import org.example.campusforum.mapper.UserMapper;
import org.example.campusforum.service.UserService;
import org.example.campusforum.utils.BaseContext;
import org.example.campusforum.utils.ErrorMessage;
import org.example.campusforum.utils.JwtUtils;
import org.example.campusforum.vo.UserInfo;
import org.example.campusforum.vo.UserReturn;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Value;

import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

import static org.example.campusforum.utils.ErrorMessage.DefaultCode;

/**
 * 用户控制器
 *
 * 处理用户相关的HTTP请求，包括用户注册、登录、信息管理、密码管理等功能。
 * 提供完整的用户账户管理功能，支持邮箱验证码验证和JWT身份认证。
 * 部分接口需要JWT认证，部分接口（如登录、注册）无需认证。
 *
 * @author CampusForum Team
 * @version 1.0
 * @since 2024
 */
@RestController
@RequestMapping("/api/user/user")
@Slf4j
public class UserController {

    /**
     * 用户服务层，处理用户相关业务逻辑
     */
    @Autowired
    private UserService userService;

    /**
     * 用户数据访问层，用于直接数据库操作
     */
    @Autowired
    private UserMapper userMapper;

    /**
     * 邮件发送服务，用于发送验证码邮件
     */
    @Autowired
    private JavaMailSender mailSender;

    /**
     * 邮箱验证码缓存映射
     * 使用ConcurrentHashMap保证线程安全，存储邮箱和对应的验证码
     */
    private static final Map<String, String> emailCodeMap = new ConcurrentHashMap<>();

    /**
     * 发件人邮箱地址，从配置文件中读取
     */
    @Value("${spring.mail.username}")
    private String fromEmail;


    /**
     * 用户登录
     *
     * 验证用户邮箱和密码，登录成功后生成JWT令牌。
     * 检查用户账户状态，确保账户未被封禁或删除。
     * 该接口无需JWT认证，在拦截器中被排除。
     *
     * @param userLogin 用户登录信息，包含邮箱和密码
     * @return 登录成功返回用户信息和JWT令牌，失败返回错误信息
     */
    @PostMapping("/login")
    public Result login(@RequestBody UserLogin userLogin) {
        log.info("用户登录请求：{}", userLogin.getEmail());

        // 根据邮箱查询用户
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getEmail, userLogin.getEmail());
        User user1 = userService.getOne(lambdaQueryWrapper);

        // 验证用户存在性和密码正确性
        if (user1 == null || !user1.getPassword().equals(userLogin.getPassword())) {
            return Result.error(ErrorMessage.wrongUsernameOrPassword);
        }

        // 检查账户状态
        if (user1.getStatus() == 2 || user1.getStatus() == 3) {
            return Result.error(ErrorMessage.accountIsBaned);
        }
        if (user1.getIsDeleted() == 2) {
            return Result.error(ErrorMessage.accountNotExist);
        }

        // 生成JWT令牌
        String token = JwtUtils.generateToken(user1.getId(), user1.getEmail());

        return Result.success(new UserReturn(user1.getId(), token, user1.getNickname()));
    }

    /**
     * 获取当前用户个人信息
     *
     * 根据JWT令牌中的用户ID查询用户的个人信息。
     * 返回用户的基本信息，不包含敏感信息如密码。
     *
     * @return 包含用户个人信息的响应结果
     */
    @GetMapping("/info")
    public Result getUserInfo() {
        log.info("获取用户个人信息");

        // 从ThreadLocal中获取当前用户ID
        Long userId = BaseContext.getCurrentId();
        if (userId == null) {
            return Result.error("用户未登录");
        }

        UserInfo userInfo = userService.getUserInfo(userId);
        if (userInfo == null) {
            return Result.error("用户不存在");
        }

        return Result.success(userInfo);
    }

    /**
     * 修改当前用户个人信息
     *
     * 更新用户的个人信息，支持部分字段更新。
     * 对输入参数进行校验，确保数据的有效性。
     * 用户ID从JWT令牌中自动获取。
     *
     * @param userUpdate 用户更新信息，包含要修改的字段
     * @return 更新结果，成功返回success，失败返回错误信息
     */
    @PutMapping("/info")
    public Result updateUserInfo(@RequestBody UserUpdate userUpdate) {
        log.info("修改用户个人信息：{}", userUpdate);

        // 从ThreadLocal中获取当前用户ID
        Long userId = BaseContext.getCurrentId();
        if (userId == null) {
            return Result.error("用户未登录");
        }

        // 参数校验
        if (userUpdate.getSex() != null && (userUpdate.getSex() < 0 || userUpdate.getSex() > 1)) {
            return Result.error("性别值无效");
        }
        if (userUpdate.getAge() != null && (userUpdate.getAge() < 1 || userUpdate.getAge() > 120)) {
            return Result.error("年龄必须在1-120之间");
        }
        if (userUpdate.getNickname() != null && userUpdate.getNickname().length() > 20) {
            return Result.error("昵称长度不能超过20个字符");
        }
        if (userUpdate.getSignature() != null && userUpdate.getSignature().length() > 100) {
            return Result.error("个性签名长度不能超过100个字符");
        }

        // 转换为User对象
        User user = User.builder()
                .nickname(userUpdate.getNickname())
                .avatar(userUpdate.getAvatar())
                .sex(userUpdate.getSex())
                .age(userUpdate.getAge())
                .signature(userUpdate.getSignature())
                .build();

        boolean success = userService.updateUserInfo(userId, user);
        if (success) {
            return Result.success("个人信息更新成功");
        } else {
            return Result.error("个人信息更新失败");
        }
    }


    /**
     * 修改密码
     *
     * 用户主动修改密码，需要验证原密码的正确性。
     * 用户ID从JWT令牌中自动获取，确保只能修改自己的密码。
     *
     * @param request 密码重置请求，包含原密码和新密码
     * @return 修改结果，成功返回success，失败返回错误信息
     */
    @PutMapping("/reset")
    public Result<Object> changePassword(@RequestBody PasswordReset request) {
        log.info("用户修改密码请求");

        // 从JWT中获取当前用户信息
        Long currentId = BaseContext.getCurrentId();
        User user = userService.getById(currentId);
        String email = user.getEmail();

        try {
            boolean result = userService.changePassword(
                    email,
                    request.getOldPassword(),
                    request.getNewPassword()
            );
            return result ? Result.success("密码修改成功") : Result.error(ErrorMessage.WRONG_OLD_PASSWORD);
        } catch (Exception e) {
            log.error("修改密码异常：", e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 忘记密码重置
     *
     * 通过邮箱验证码验证用户身份后，重置用户密码为默认密码。
     * 无需验证原密码，适用于用户忘记密码的场景。
     * 该接口无需JWT认证，在拦截器中被排除。
     *
     * @param request 忘记密码请求，包含邮箱、新密码和验证码
     * @return 重置结果，成功返回success，失败返回错误信息
     */
    @PutMapping("/forget")
    public Result<Object> resetPassword(@RequestBody UserForget request) {
        log.info("忘记密码重置请求：{}", request.getEmail());

        String requestEmail = request.getEmail();

        // 验证验证码是否存在且未过期
        if (!emailCodeMap.containsKey(requestEmail)) {
            return Result.error("验证码已过期");
        }

        // 验证验证码是否正确
        String code = emailCodeMap.get(requestEmail);
        if (!code.equals(request.getVerificationCode())) {
            return Result.error("验证码错误");
        }

        // 重置密码为默认密码
        User user1 = new User();
        BeanUtil.copyProperties(request, user1);
        user1.setPassword(DefaultCode);

        boolean success = userService.resetForgottenPassword(request.getEmail(), user1.getPassword());

        // 清除已使用的验证码
        emailCodeMap.remove(request.getEmail());

        return success ? Result.success("密码重置成功") : Result.error("密码重置失败");
    }

    /**
     * 用户注册
     */
    @PostMapping("/register")
    public Result register(@RequestBody UserRegister user) {
        log.info("开始用户注册");
        if (user.getEmail() == null || user.getEmail().isEmpty()) {
            return Result.error("邮箱不能为空");
        }
        if (user.getPassword() == null || user.getPassword().isEmpty()) {
            return Result.error("密码不能为空");
        }
        if (user.getNickname() == null || user.getNickname().isEmpty()) {
            return Result.error("昵称不能为空");
        }
        if (user.getEmail().length() > 50) {
            return Result.error("邮箱长度不能超过50个字符");
        }
        if (user.getPassword().length() > 20) {
            return Result.error("密码长度不能超过20个字符");
        }
        if (user.getNickname().length() > 20) {
            return Result.error("昵称长度不能超过20个字符");
        }

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, user.getEmail());
        if (userMapper.selectOne(queryWrapper) != null) {
            return Result.error("邮箱已存在");
        }

        if (!emailCodeMap.containsKey(user.getEmail())) {
            return Result.error("验证码已过期");
        }
        String code = emailCodeMap.get(user.getEmail());
        if (!code.equals(user.getVerificationCode())) {
            return Result.error("验证码错误");
        }

        User user1 = new User();
        BeanUtil.copyProperties(user, user1);
        userService.registerUser(user1);
        emailCodeMap.remove(user.getEmail());
        return Result.success("注册成功");
    }

    public String getVerificationCode() {
        Random random = new Random();
        String charPool = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String captcha = "";
        for (int i = 0; i < 5; i++) {
            int index = random.nextInt(charPool.length());
            captcha += charPool.charAt(index);
        }
        System.out.println("生成的验证码: " + captcha);
        return captcha;
    }

//    public Result sendEmail(ToEmail toEmail) {
//        //创建简单邮件消息
//        SimpleMailMessage message = new SimpleMailMessage();
//        //谁发的
//        message.setFrom(toEmail.getFrom());
//        String verificationCode = getVerificationCode();
//        toEmail.setContent(verificationCode);
//        //谁要接收
//        message.setTo(toEmail.getTos());
//        //邮件标题
//        message.setSubject(toEmail.getSubject());
//        //邮件内容
//        message.setText(toEmail.getContent());
//        try {
//            mailSender.send(message);
//            return Result.success(toEmail.getTos() + "发送普通邮件成功");
//        } catch (MailException e) {
//            e.printStackTrace();
//            return Result.error("普通邮件方失败");
//        }
//    }

    /**
     * 发送登录验证码到邮箱
     */
    @PostMapping("/sendLoginCode")
    public Result sendLoginCode(@RequestBody ToEmail toEmail) {
        String code = getVerificationCode();

        emailCodeMap.put(toEmail.getTos(), code);

        SimpleMailMessage message = new SimpleMailMessage();
        // 谁发的
        message.setFrom(fromEmail);
        // 谁要接收
        message.setTo(toEmail.getTos());
        message.setSubject("登录验证码");
        message.setText("您的验证码是：" + code + "，有效期5分钟。");

        try {
            mailSender.send(message);
            return Result.success("验证码已发送");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("验证码发送失败");
        }
    }
}


